#ifndef _USTC_USB_BULK_H_
#define _USTC_USB_BULK_H_

#define CSW_GOOD        0x00
#define CSW_FAIL        0x01
#define CSW_PHASE_ERROR 0x02

#define CBW_SIGNATURE   0x43425355
#define CSW_SIGNATURE   0x53425355


#define CBW_FLAG_IN     0x80

#define MAX_CDBLEN      0x10

typedef PACKED_REMOVED struct _COMMAND_BLOCK_WRAPPER{
    USTC_U32   dCBW_Signature;
    USTC_U32   dCBW_Tag;
    USTC_U32   dCBW_DataXferLen;
    USTC_U8    bCBW_Flag;
    USTC_U8    bCBW_LUN;
    USTC_U8    bCBW_CDBLen;
//	USTC_U8	 resv0;
    CDB	     cdb;
}CBW, *PCBW;

typedef PACKED/*PACKED_REMOVED*/ struct _COMMAND_STATUS_WRAPPER{
    USTC_U32   dCSW_Signature;
    USTC_U32   dCSW_Tag;
    USTC_U32   dCSW_DataResidue;
    USTC_U8    bCSW_Status;
//	USTC_U8	 resv[3];
} CSW, *PCSW;

typedef union _BULK_HEADER {
    CBW     cbw;
    CSW     csw;
} BULK_HEADER_T, * PBULK_HEADER_T;

//
// Host Device Disagreement Matrix
//
enum  {
	CASEOK = 0,
	CASE1,
	CASE2,
	CASE3,
	CASE4,
	CASE5,
	CASE6,
	CASE7,
	CASE8,
	CASE9,
	CASE10,
	CASE11,
	CASE12,
	CASE13,
	CASECBW,
	CASECMDFAIL
};

typedef struct _USB_PARA_T_
{
	//select usb mode: 0pc sync  1 pc camera 2 virtual serial port 3 udisk
	USTC_U8 	usb_mode;
	USTC_U8	disk;
	USTC_U8	udisk_retry_count;
	USTC_U8	resv1;
	
	USTC_U16	usb_vendor[32];
	USTC_U16	usb_product[32];
	USTC_U16	usb_vendor_size;//vendor string when enum, unicode; vendor max 32 unicode char; also use as one global buffer for reponse PC
	USTC_U16	usb_product_size;//product string

	USTC_U8 	udisk_vendor[8];//udisk vendor/product string, ASCII
	USTC_U8 	udisk_product[16];
	
	/*for multi-partition support*/

	/*each disk's property; 
	bit0: 1 write protected
	bit1: 1 locked
	bit2: 1 cdrom/0 removeable disk
	*/
	USTC_U8	udisk_disk_flag[16];
	USTC_U32	udisk_disk_start[16];
	USTC_U32 	udisk_disk_size[16];
	USTC_U8	udisk_disk_num[4];//lun number;  total disk in udisk mode, 0 for SD; 1 for Nandflash 2 for host 3 reserved
	USTC_U8	udisk_password_flag[4]; //0  no password 1 password protected
	USTC_U32	psector[4];
	USTC_U32	isector[4];
	USTC_U8	pwd_encrypt[32];

	USTC_U16 (*read[4])(unsigned long *data, unsigned long blk, unsigned long cnt);
	USTC_U16 (*write[4])(unsigned long *data, unsigned long blk, unsigned long cnt);
	USTC_U16 (*clear[4])(unsigned long blk, unsigned long cnt);
}USB_PARA_T;

typedef	PACKED_REMOVED struct
{
	USTC_U8	bRequestType;
	USTC_U8	bRequest;
	USTC_U16	wValue;
	USTC_U16	wIndex;
	USTC_U16	wLength;
}DEVICE_REQUEST_T;

#define	MAX_CONTROLDATA_SIZE	64
#define EP0_PACKET_SIZE 		64
#define EP1_PACKET_SIZE 		64
#define	MAX_CACHE_BLOCK			64
//#define	MAX_CACHE_BLOCK			16
#define BOTFSM_IDLE				0
#define BOTFSM_CBW				1
#define BOTFSM_DATAIN			2
#define BOTFSM_DATAOUT			3
#define BOTFSM_CSW				4
#define BOTFSM_STALL			5

typedef struct _PARA_USB_GLOABL_
{
	USTC_U16 command;
	USTC_U16 host_id;
	USTC_U8 exit_flag;
	USTC_U8 usb_mode;	//select usb mode: 0 udisk 1 pc camera 2 pc sync 3 virtual serial port	
	USTC_U8 vserial_enable;
	USTC_U8 sys_startmode;
}PARA_USB_GLOABL;

typedef	struct
{
	DEVICE_REQUEST_T	DeviceRequest;	//DEVICE REQUEST
	USTC_U16	wLength;		//total length to transfer
	USTC_U16	wCount;			//actual length to transfer
	USTC_U8	*pData;			//point to transfer data
	USTC_U8	dataBuffer[MAX_CONTROLDATA_SIZE];	//reqest data
} CONTROL_DATA_T;

typedef struct _USB_PATH_T_
{
	//parameters
	USB_PARA_T	*p_para_usb;

	//status
	USTC_U32	usb_status;//usb status;return to host when query

	CONTROL_DATA_T control_data; //control data

	//control 
	USTC_U8	usb_loop_flag;// usb loop flag, determine usb dead loop's run or exit
	USTC_U8	usb_exit_flag;//quit usb mode
	
	USTC_U8	configuration;
	USTC_U8	setup_packet;
	USTC_U8	control_state;
	USTC_U8	bot_state;
	USTC_U8	in_tx;
	USTC_U8	ep_rxdone;
	USTC_U8	ep_txdone;

	//data buffer
	USTC_U8	ep_rx_len;
	USTC_U8	ep_tx_len;
	USTC_U8	resv1;
	USTC_U8	ep_buff_rx[EP0_PACKET_SIZE];//dma buffer for rx(ep0/ep1)

	USTC_U8	ep_buff_tx[EP0_PACKET_SIZE];//tempray store tx data of application
	

	USTC_U8	*ep_buff_retry;
	USTC_U8	*usb_cache;//cache buffer for sector data

	//for bulk only transfer (udisk)
	BULK_HEADER_T	bulk_hdr;
	
	USTC_U32	usb_start_lba;//READ/WRITE sector start LBA
	USTC_U32	usb_sec_num;//read/write sector number
	USTC_U32	usb_sec_off;//current read/write position in one sector
	USTC_U32	sec_num;//current total block number in cache(read multiblock from SD card)

	USTC_U8	*bot_data; //transfer data buffer address
	USTC_U32	bot_len;//total length to transfer (bytes)
	USTC_U32	bot_len_transfer;// total length have transfed(bytes)

	USTC_U8	udisk_disk_src;
	USTC_U8	udisk_disk_index;

	//for pc camera
	USTC_U8	pccam_preview_on;
	USTC_U8	pccam_zero_pkt;

}USB_PATH_T;

//
//FUNCTIONS
//
void 	bulk_cbw_handler( void );
void 	bulk_csw_handler( void );

int 	bulk_is_cbw_valid(USTC_U8* buf,USTC_U8 len);
void 	bulk_set_csw_status(USTC_U8 HostDevCase,USTC_U16 len);

STATUS_T usbboot_read_multi_block(void * p_buffer, unsigned int block_index,unsigned int block_num);
STATUS_T usbboot_write_multi_block(void * p_buffer, unsigned int block_index,unsigned int block_num);

void 	bulk_data_out_handler(void);
void 	bulk_data_in_handler(void);

extern PARA_USB_GLOABL g_ustc_usb_contorl;
#endif
